package com.xquant.trade.trade.service.impl;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.alibaba.fastjson2.JSONArray;
import com.github.pagehelper.PageInfo;
import com.xquant.common.core.constant.ErrMsgConstant;
import com.xquant.common.core.exception.ServiceException;
import com.xquant.common.core.utils.ParseUtils;
import com.xquant.common.engine.xPP.cxf.XQuantPPService;
import com.xquant.common.engine.xPP.request.CalcEngineParam;
import com.xquant.common.engine.xPP.request.CalcPricingParam;
import com.xquant.common.engine.xPP.request.Instrument;
import com.xquant.common.engine.xPP.response.CalcMarket;
import com.xquant.common.engine.xPP.response.CalcPaymentInfo;
import com.xquant.common.engine.xPP.response.Contract;
import com.xquant.common.security.utils.SecurityUtils;
import com.xquant.trade.account.mapper.AccountMapper;
import com.xquant.trade.utils.ResponseVo;
import com.xquant.trade.risk.entity.CombinedMonitorDetail;
import com.xquant.trade.risk.service.RiskService;
import com.xquant.trade.trade.entity.Trade;
import com.xquant.trade.trade.mapper.TequityStructureMapper;
import com.xquant.trade.trade.mapper.TradeMapper;
import com.xquant.trade.trade.service.SettleService;
import com.xquant.trade.utils.CacheUtil;
import com.xquant.trade.utils.CommResponse;
import com.xquant.trade.utils.DateUtils;
import com.xquant.trade.utils.SysUtils;
import com.xquant.system.api.RemoteDailyPriceService;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang.StringUtils;
import org.quartz.JobExecutionContext;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.lang.NonNull;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.*;

@Component
public class DurationServiceImpl {
    @Autowired
    private TradeMapper tradeMapper;
    @Autowired
    private TradeServiceFactory tradeServiceFactory;
    @Autowired
    private AccountMapper accountMapper;
    @Autowired
    private SettleService settleService;
    @Autowired
    private XQuantPPService ppService;
    @Autowired
    private RiskService riskService;
    @Autowired
    private TequityStructureMapper tequityStructureMapper;
    @Autowired
    private RemoteDailyPriceService dailyPriceService;

    //IO线程工厂类
    static ThreadFactory threadFactory = new  ThreadFactory() {
        @Override
        public Thread newThread(@NonNull Runnable runnable) {
            Thread thread = new Thread(runnable);
            thread.setName("calcTpAll-pool-");
            return thread;
        }
    };
    private static ThreadPoolExecutor executors = new ThreadPoolExecutor(10,
            20,
            60,
            TimeUnit.SECONDS,
            new LinkedBlockingQueue<Runnable>(Integer.MAX_VALUE),threadFactory,new ThreadPoolExecutor.DiscardPolicy());
    /**
     * 查询 交易日历事件列表（期权交易）  到期 敲入 敲出 触碰
     */
    public List queryAllTradeRemind() {
        List<Map> lst = tradeMapper.queryAllTremind();
        return (lst);
    }

    public List<Map> query30DaysTradeRemind(Map map) {
        List<Map> lst = tradeMapper.query30DayTremind(map);
        return (lst);
    }

    /**
     * 查询到期交易  期权交易
     */
    public PageInfo<Map> queryExpireContract(Map map) {
        List<Map> lst = tradeMapper.queryExpireContract(map);
        return new PageInfo<>(lst);
    }

    /**
     * 交易批量估值计算 任务调度
     */
    public void calTask(JobExecutionContext jobExecutionContext) throws ParseException {
        Map param = new HashMap();
        String begDate = MapUtils.getString(jobExecutionContext.getMergedJobDataMap(), "begDate");
        String endDate = MapUtils.getString(jobExecutionContext.getMergedJobDataMap(), "endDate");
        if (begDate != null && endDate != null) {
            List<String> days = DateUtils.getRangeDate(begDate, endDate);
            days.stream().forEach(data -> {
                param.put("calcDate", data);
                try {
                    calcTrade4OtcOptionByPage(param);
                } catch (ServiceException e) {
                    throw new ServiceException(ErrMsgConstant.CALC_TASK_ERR,e.getMessage());
                }
            });
        } else {
            String blcDate = riskService.getBlcDate();
            param.put("calcDate", blcDate);
            calcTrade4OtcOptionByPage(param);
        }

    }

    /**
     * 交易批量估值计算
     */
    public CommResponse calcTrade4OtcOptionByPage(Map param) throws ServiceException {
        if (ppService.getThreads() == 0) {
            throw new RuntimeException("无可用的计算服务，请检查");
        }

        param.put("userId", "admin");
        param.put("priceType", "DP_CLOSE");
        CacheUtil.getInstance().removeAllCacheData();
        List<CombinedMonitorDetail> successList = new ArrayList();
        List<Map> errorList = new ArrayList();
        //计算
        List<CombinedMonitorDetail> resultList = calcOtcOption(successList, errorList, param);
        CacheUtil.getInstance().removeAllCacheData();

        for (CombinedMonitorDetail combinedMonitorDetail : resultList) {
            CombinedMonitorDetail detail = new CombinedMonitorDetail();
            BeanUtils.copyProperties(combinedMonitorDetail,detail);
            detail.setCalcBy(SecurityUtils.getUserId());
            detail.setTradeId(combinedMonitorDetail.getTradeId());
            detail.setCalcDate(combinedMonitorDetail.getCalcDate());
            detail.setOperateDate(DateUtils.getCurr_YYYY_MM_DD());
            detail.setCalcTime(DateUtils.getCurr_YYYY_MM_DD_HH_MM_SS_SSS());
            SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
            if (combinedMonitorDetail.getMaturityDate() != null) {
                String calcDate=(String) param.get("calcDate");
                if(StrUtil.isEmpty(calcDate)){
                    calcDate=settleService.getBlcDate();
                }
                try {
                    if (format.parse(combinedMonitorDetail.getIssueDate()).getTime() > format.parse(calcDate).getTime()) {
                        detail.setEventStatus(null);
                    }
                    if ( format.parse(combinedMonitorDetail.getMaturityDate()).getTime() < format.parse(calcDate).getTime()) {
                        String status = tradeMapper.queryEventStatus(detail);
                        if (status != null) {
                            detail.setEventStatus(status);
                        }
                    }
                    if (format.parse(combinedMonitorDetail.getIssueDate()).getTime() <= format.parse(calcDate).getTime() && format.parse(combinedMonitorDetail.getMaturityDate()).getTime() >= format.parse(calcDate).getTime()) {
                        String status = tradeMapper.queryEventStatusLast(detail);
                        if (status != null) {
                            detail.setEventStatus(status);
                        }
                    }
                }catch (ParseException e){
                    throw new ServiceException(ErrMsgConstant.CALC_MUILT_ERR);
                }
            }
            if (tradeMapper.selectEquityDurationCount(detail) > 0) {
                tradeMapper.updateTequityDuration(detail);
            } else {
                tradeMapper.insertTequityDuration(detail);
            }
        }
        return CommResponse.success();
    }

    public List<CombinedMonitorDetail> calcOtcOption(List<CombinedMonitorDetail> successList, List<Map> errorList, Map param) throws ServiceException {
        List<CombinedMonitorDetail> result = new ArrayList<>();
        String calcDate = MapUtil.getStr(param, "calcDate");
        String blcDate = settleService.getBlcDate();
        param.put("blcDate", ObjectUtil.isNotNull(calcDate) ? calcDate : blcDate);
        //查询计算列表
        List<Trade> otcOptionBalance = tradeMapper.querySimpBalance4OtcOptionByPage(param);
        PageInfo otcOptionBalancePg = new PageInfo<>(otcOptionBalance);
        param.put("total", otcOptionBalancePg.getTotal());
        //20220803 botao.yu 批量计算性能优化
        if(otcOptionBalance.size()>0){
            List<Callable<CombinedMonitorDetail>> tasks = new ArrayList<Callable<CombinedMonitorDetail>>();//添加任务
            for (int i = 0; i < otcOptionBalance.size(); i++) {
                Trade blc = otcOptionBalance.get(i);
                Callable<CombinedMonitorDetail> qfe = new Callable<CombinedMonitorDetail>() {
                    @Override
                    public CombinedMonitorDetail call() throws Exception {
                        //return calcOtcOptionResult(blc, ObjectUtil.isNotNull(calcDate) ? calcDate : blcDate);
                        return new CombinedMonitorDetail();
                    }
                };
                tasks.add(qfe);
            }
            List<Future<CombinedMonitorDetail>> futures = null;
            try {
                futures = executors.invokeAll(tasks);
            } catch (InterruptedException e) {
                throw new ServiceException(ErrMsgConstant.CALC_MUILT_ERR);
            }
            if (futures != null && futures.size() > 0) {
                for (Future<CombinedMonitorDetail> future : futures) {
                    CombinedMonitorDetail item= null;
                    try {
                        item = future.get();
                    } catch (InterruptedException e) {
                        throw new ServiceException(ErrMsgConstant.CALC_MUILT_ERR);
                    } catch (ExecutionException e) {
                        throw new ServiceException(ErrMsgConstant.CALC_MUILT_ERR);
                    }
                    if (item == null) {
                        continue;
                    }
                    result.add(item);
                    if (StringUtils.isNotEmpty(item.getErrInfo())) {
                        Map m = new HashMap();
                        m.put("iCode", item.getiCode());
                        m.put("errInfo", item.getErrInfo());
                        synchronized (errorList) {
                            errorList.add(m);
                        }
                    } else {
                        synchronized (successList) {
                            successList.add(item);
                        }
                    }
                }
            }
        }


        return result;
    }

    private CombinedMonitorDetail calcOtcOptionResult(Trade blc, String blcDate) {

        CombinedMonitorDetail tmp = new CombinedMonitorDetail();

        Map map = new HashMap();
        map.put("blcDate", blcDate);
        double eval = 0.00;
        double npv = 0.00;
        double delta = 0.00;
        double gamma = 0.00;
        double vega = 0.00;
        double rho = 0.00;
        double theta = 0.00;
        double cashDelta = 0.00;
        double cashGamma = 0.00;
        try {
            tmp.setTradeId(blc.getTradeId());
            tmp.setTradeType(blc.getTradeType());
            tmp.setuICode(blc.getuICode());
            tmp.setuAType(blc.getuAType());
            tmp.setuMType(blc.getuMType());
            tmp.setuIName(blc.getuIName());
            tmp.setiName(blc.getuIName());
            tmp.setLotSize(1);
            tmp.setCalcDate(blcDate);
            //场内交易
            if (!StrUtil.equals("CTM", blc.getaType())) {
                // 设置code
                tmp.setiCode(null);
                tmp.setaType(null);
                tmp.setmType(null);
                tmp.setVolume(blc.getVolume().doubleValue());
                tmp.setProductType(blc.getProductType());

                tmp.setCalcPrice(blc.getuPrice());
                if (blc.getuICode().indexOf("510050") > -1 || blc.getuICode().indexOf("510300") > -1 || blc.getuICode().indexOf("159919") > -1) {
                    tmp.setVolume(blc.getVolumeNum().doubleValue() * blc.getOldPrice() * 10000);
                    tmp.setLotSize(10000);
                    tmp.setNpv(blc.getuPrice() * blc.getVolumeNum().doubleValue() * 10000);
                    tmp.setDelta(blc.getVolumeNum().doubleValue() * 10000);
                } else {
                    tmp.setLotSize(1);
                    tmp.setVolume(blc.getVolumeNum().doubleValue() * blc.getOldPrice() * 1);
                    tmp.setNpv(blc.getuPrice() * blc.getVolumeNum().doubleValue() * 1);
                    tmp.setDelta(blc.getVolumeNum().doubleValue());
                }
                if (StrUtil.equals("LongOpen", tmp.getTradeType())) {
                    tmp.setDelta(Math.abs(tmp.getDelta()));
                    tmp.setNpv(Math.abs(tmp.getNpv()));
                } else {
                    tmp.setDelta(-Math.abs(tmp.getDelta()));
                    tmp.setNpv(-Math.abs(tmp.getNpv()));
                }
                if (tmp.getVolume() == 0) {
                    tmp.setHisYield(0.00);
                } else {
                    tmp.setHisYield((Math.abs(tmp.getNpv()) - Math.abs(tmp.getVolume())) / Math.abs(tmp.getVolume()));
                }
                tmp.setCashDelta(NumberUtil.mul(tmp.getDelta(), blc.getuPrice()));
                //场外期权
            } else {
                tmp.setiCode(blc.getiCode());
                tmp.setaType(blc.getaType());
                tmp.setmType(blc.getmType());
                tmp.setProductType(blc.getProductType());
                tmp.setVolume(blc.getVolume().doubleValue());
                tmp.setIssueDate(blc.getIssueDate());
                tmp.setMaturityDate(blc.getMaturityDate());
                tmp.setMarginCost(blc.getMarginCost().doubleValue());
                tmp.setProductName(blc.getProductName());
                tmp.setDimAccId(blc.getDimAccId());
                tmp.setAccId(blc.getAccId());
                tmp.setAccName(blc.getAccName());
                tmp.setAccIdCp(blc.getAccIdCp());
                tmp.setAccNameCp(blc.getAccNameCp());
                tmp.setpCalc(blc.getpCalc());
                tmp.setExerciseType(blc.getExerciseType());
                tmp.setPremium(blc.getPremium());

                // 设置uCode
                Instrument instrument = JSON.parseObject(MapUtils.getString(blc.getInstrumentInfo(), "pCalc"), Instrument.class);
                if (ObjectUtil.isNull(instrument) || ObjectUtil.isNull(instrument.getTermsheet())) {

                }

                CalcPricingParam calcPricingParam = new CalcPricingParam();
                calcPricingParam.setValueDate(blcDate);
                CalcEngineParam calcEngineParam = new CalcEngineParam();

                calcEngineParam.setInstrument(instrument);
                calcEngineParam.setCalcPricingParam(calcPricingParam);

                /*******************************计算 估值 现金流**********************************/

                //ResponseVo resYield = calcEngineService.calcEngineByCfgId(ProductTypeEnum.OTC_OPTION.getCode(), RequestCodeEnum.CALC_PAYMENTINFO.getCode(), calcEngineParam);
               // ResponseVo res = calcEngineService.calcEngineByCfgId(ProductTypeEnum.OTC_OPTION.getCode(), RequestCodeEnum.CALC_MARKET.getCode(), calcEngineParam);
                ResponseVo resYield = ResponseVo.success();
                ResponseVo res = ResponseVo.success();
                if (blc.getMaturityDate() != null && Convert.toInt(blc.getMaturityDate().replace("-", "")) <= Convert.toInt(blcDate.replace("-", "")) ||
                        (blc.getRemindDate() != null && Convert.toInt(blc.getRemindDate().replace("-", "")) <= Convert.toInt(blcDate.replace("-", "")))) {
                    if (resYield.getErrorCode() > -1&&resYield.getResult()!=null) {
                        CalcPaymentInfo calcPaymentInfo = ((CalcPaymentInfo) ((ArrayList) resYield.getResult()).get(0));
                        if (calcEngineParam.getInstrument().getProductType().indexOf("ELN") > -1) {
                            tmp.setRealizedYield(NumberUtil.div(Convert.toDouble(calcPaymentInfo.getAmount()), calcEngineParam.getInstrument().getTermsheet().getDouble("notional")));
                            tmp.setHisYield(NumberUtil.div(Convert.toDouble(calcPaymentInfo.getAmount()), calcEngineParam.getInstrument().getTermsheet().getDouble("notional")));
                        } else {
                            tmp.setRealizedYield(NumberUtil.div(Convert.toDouble(calcPaymentInfo.getAmount()), calcEngineParam.getInstrument().getTermsheet().getDouble("notional")));
                            tmp.setHisYield(NumberUtil.div(Convert.toDouble(calcPaymentInfo.getAmount()), calcEngineParam.getInstrument().getTermsheet().getDouble("notional")));
                        }
                    }
                }
                //判断到期状态
                if (blc.getMaturityDate() != null && Convert.toInt(blc.getMaturityDate().replace("-", "")) <= Convert.toInt(blcDate.replace("-", ""))) {
                    tmp.setExerciseAmount(blc.getVolume().doubleValue());
                }
                if (resYield.getErrorCode() > -1&&resYield.getResult()!=null) {
                    CalcPaymentInfo calcPaymentInfo = ((CalcPaymentInfo) ((ArrayList) resYield.getResult()).get(0));
                    if (calcEngineParam.getInstrument().getProductType().indexOf("ELN") > -1) {
                        tmp.setRealizedYield(NumberUtil.div(Convert.toDouble(calcPaymentInfo.getAmount()), calcEngineParam.getInstrument().getTermsheet().getDouble("notional")));
                        tmp.setHisYield(NumberUtil.div(Convert.toDouble(calcPaymentInfo.getAmount()), calcEngineParam.getInstrument().getTermsheet().getDouble("notional")));
                    } else {
                        tmp.setRealizedYield(NumberUtil.div(Convert.toDouble(calcPaymentInfo.getAmount()), calcEngineParam.getInstrument().getTermsheet().getDouble("notional")));
                        tmp.setHisYield(NumberUtil.div(Convert.toDouble(calcPaymentInfo.getAmount()), calcEngineParam.getInstrument().getTermsheet().getDouble("notional")));
                    }
                }

                if (res.getErrorCode() < 0) {
                    tmp.setErrInfo(res.getErrorMsg());
                    tmp.setErrCode(StrUtil.toString(res.getErrorCode()));
                } else {
                    //单位化
                    boolean dwh = false;
                    Contract contract = ((CalcMarket) res.getResult()).getContract();
                    if (calcEngineParam.getInstrument().getProductType().indexOf("ELN") > -1) {
                        eval = Double.parseDouble(contract.getNpv());
                        npv = Double.parseDouble(contract.getNpv());
                        delta = Double.parseDouble(contract.getDelta());
                        gamma = Double.parseDouble(contract.getGamma());
                        vega = Double.parseDouble(contract.getVega());
                        rho = Double.parseDouble(contract.getRho());
                        theta = Double.parseDouble(contract.getTheta());
                        cashDelta = Double.parseDouble(contract.getDelta()) * Double.parseDouble(contract.getSpotPrice());
                        cashGamma = Double.parseDouble(contract.getGamma()) * Double.parseDouble(contract.getSpotPrice()) * Double.parseDouble(contract.getSpotPrice()) / 100;

                    } else {
                        if (dwh) {

                            eval = Double.parseDouble(contract.getNpv()) * blc.getVolume().doubleValue();
                            npv = Double.parseDouble(contract.getNpv()) * blc.getVolume().doubleValue();
                            delta = Double.parseDouble(contract.getDelta()) * blc.getVolume().doubleValue();
                            gamma = Double.parseDouble(contract.getGamma()) * blc.getVolume().doubleValue();
                            vega = Double.parseDouble(contract.getVega()) * blc.getVolume().doubleValue();
                            rho = Double.parseDouble(contract.getRho()) * blc.getVolume().doubleValue();
                            theta = Double.parseDouble(contract.getTheta()) * blc.getVolume().doubleValue();
                            cashDelta = Double.parseDouble(contract.getDelta()) * Double.parseDouble(contract.getSpotPrice()) * blc.getVolume().doubleValue();
                            cashGamma = Double.parseDouble(contract.getGamma()) * Double.parseDouble(contract.getSpotPrice()) * Double.parseDouble(contract.getSpotPrice()) * blc.getVolume().doubleValue() / 100;

                        } else {
                            eval = Double.parseDouble(contract.getNpv());
                            npv = Double.parseDouble(contract.getNpv());
                            delta = Double.parseDouble(contract.getDelta());
                            gamma = Double.parseDouble(contract.getGamma());
                            vega = Double.parseDouble(contract.getVega());
                            rho = Double.parseDouble(contract.getRho());
                            theta = Double.parseDouble(contract.getTheta());
                            cashDelta = Double.parseDouble(contract.getDelta()) * Double.parseDouble(contract.getSpotPrice());
                            cashGamma = Double.parseDouble(contract.getGamma()) * Double.parseDouble(contract.getSpotPrice()) * Double.parseDouble(contract.getSpotPrice()) / 100;

                        }

                    }
                    //20220728 botao,yu  支持浮动盈亏的计算 去除前端费和期权费的成本 已实现收益率只计算收益 不扣减成本
                    //tmp.setRealizedYield();
                    //tmp.setHisYield()
                    tmp.setPlFloat(eval - blc.getAmountCost().doubleValue());
                    //如果前端费支付日和期权费支付日小于等于计算日，则浮动盈亏始终减去成本(包含前端费和期权费)
                    JSONObject formData=JSON.parseObject(MapUtils.getString(blc.getInstrumentInfo(), "pForm"));
                    String frontFeeDate=formData.getString("frontFeePaydate");
                    Double front = formData.getDouble("frontFee") == null ? 0.0D : formData.getDouble("frontFee");
                    BigDecimal frontFee=new BigDecimal(front);
                    String frontOptionFeeDate=formData.getString("frontOptionFeePaydate");
                    Double frontOption = formData.getDouble("frontOptionFee") == null ? 0.0D : formData.getDouble("frontOptionFee");
                    BigDecimal frontOptionFee=new BigDecimal(frontOption);
                    //费用有正负 以界面录入为准 后台不作判断
                    if(frontFee.compareTo(BigDecimal.ZERO)!=0&&StrUtil.isNotBlank(frontFeeDate)&& DateUtil.compare(DateUtil.parseDate(frontFeeDate),DateUtil.parseDate(blcDate))<=0){
                        tmp.setPlFloat((new BigDecimal(tmp.getPlFloat()).add(frontFee)).doubleValue());
                    }
                    if(frontOptionFee.compareTo(BigDecimal.ZERO)!=0&&StrUtil.isNotBlank(frontOptionFeeDate)&& DateUtil.compare(DateUtil.parseDate(frontOptionFeeDate),DateUtil.parseDate(blcDate))<=0){
                        tmp.setPlFloat((new BigDecimal(tmp.getPlFloat()).add(frontOptionFee)).doubleValue());
                    }
                    tmp.setGroupInfo(blc.getuICode());
                    tmp.setVolume(blc.getVolume().doubleValue());
//                    tmp.setPlFloat(eval - blc.getAmountCost().doubleValue());
                    tmp.setNpv(npv);
                    tmp.setDelta(delta);
                    tmp.setGamma(gamma);
                    tmp.setVega(vega);
                    tmp.setRho(rho);
                    tmp.setTheta(theta);
                    tmp.setCashDelta(cashDelta);
                    tmp.setCashGamma(cashGamma);
                    //xpp 存在计算结果中没有信息的情况，这里改成从计算参数取
                    if (ObjectUtil.isNotNull(calcEngineParam.getCalcPricingParam().getUnderlyingPricingParams())&&calcEngineParam.getCalcPricingParam().getUnderlyingPricingParams().size()!=0){
                        String spotPrice = calcEngineParam.getCalcPricingParam().getUnderlyingPricingParams().get(0).getSpotPrice();
                        tmp.setCalcPrice(Double.parseDouble(spotPrice));
                    }else {
                        tmp.setCalcPrice(Double.parseDouble(contract.getSpotPrice()));
                    }

                }
            }

        } catch (Exception ex) {
            ex.printStackTrace();
            tmp.setErrCode("-999");
            tmp.setErrInfo(SysUtils.getErrorMsg(ex));

        }
        return tmp;
    }

    public List<Map> queryTradeCalendarDates(Map params) {
        return tradeMapper.queryTCalendarDates(params);
    }


    public List<Map> queryTradeCalendar(Map params) {
        return tradeMapper.queryTCalendar(params);
    }


    public void updateTradeCalendarDates(Map params) {
        tradeMapper.updateTCalendarDates(params);
    }

    public void updateTradeCalendarDatesByYear(Map params) {
        tradeMapper.updateTCalendarDatesByYear(params);
    }

    public void insertTCalendarDatesIfNotExist(Map params) {
        tradeMapper.insertTCalendarDatesIfNotExist(params);
    }

    public void insertTCalendarDatesIfNotExistByYear(Map params) {
        tradeMapper.insertTCalendarDatesIfNotExistByYear(params);
    }


    public List<Trade> queryTodayTrade4OtcOptionByPage(Map map) {
        return tradeMapper.queryTradeDuration4OtcOptionByPage(map);
    }

    //查询date的上一个交易日，并且计算两个日期差多少天
    public Integer queryLastCalDayDiff(Date date) {
        String dateString = new SimpleDateFormat("yyyy-MM-dd").format(date);
        Map<String, Object> map = new HashMap<>();
        map.put("calCode", "CHINA_EX");
        map.put("day", dateString);
        Map resultMap = tradeMapper.queryLastCalDay(map);
        if (resultMap.get("CAL_DAY") != null) {
            return DateUtils.getDateBetweenDiffer(dateString, (String) resultMap.get("CAL_DAY"));
        }
        return 0;
    }
    public void setSpotPrice(JobExecutionContext jobExecutionContext) throws ParseException {
        String begDate = MapUtils.getString(jobExecutionContext.getMergedJobDataMap(), "begDate");
        String endDate = MapUtils.getString(jobExecutionContext.getMergedJobDataMap(), "endDate");
        if (begDate != null && endDate != null) {
            HashMap<String, String> map = new HashMap<>();
            map.put("begDate",begDate);
            map.put("endDate",endDate);
            doSetSpotPrice(map);
        } else {
            HashMap<String, String> map = new HashMap<>();
            String blcDate = riskService.getBlcDate();
            map.put("endDate", blcDate);
            doSetSpotPrice(map);
        }
    }

    private void doSetSpotPrice(Map<String,String> map) {
        List<Map> list = tequityStructureMapper.queryTradeListPriceOnWait(map);
        for (Map structMap : list) {
            HashMap<String, Object> dayMap = new HashMap<>();
            dayMap.put("iCode", structMap.get("U_I_CODE"));
            dayMap.put("aType", structMap.get("U_A_TYPE"));
            dayMap.put("mType", structMap.get("U_M_TYPE"));
            dayMap.put("begDate", structMap.get("ISSUE_DATE"));
            Map resultMap = dailyPriceService.getdailypriceByBegDate(dayMap);
            if (resultMap == null || resultMap.get("error") != null) {

            } else {
                BigDecimal dpClose = ParseUtils.converToBigDecimal(resultMap.get("dpClose"));
                String pCalc = (String) structMap.get("P_CALC");
                String pForm = (String) structMap.get("P_FORM");
                String pFormInstrument = (String) structMap.get("P_FORM_INSTRUMENT");
                Instrument instrument = JSONObject.parseObject(pCalc, Instrument.class);
                JSONObject termsheet = instrument.getTermsheet();
                JSONArray customLegs = (JSONArray) instrument.getTermsheet().get("customLegs");
                JSONObject customLeg = (JSONObject) customLegs.get(0);
                BigDecimal notinal = ParseUtils.converToBigDecimal(termsheet.get("notional"));
                JSONArray underlyers = (JSONArray) customLeg.get("underlyers");
                JSONObject underlyer = (JSONObject) underlyers.get(0);
                HashMap<String, Object> updateMap = new HashMap<>();

                if (customLeg.get("productType").equals("RangeAccrual")) {
                }

                // 更新struct的行权价（香草、二元、双层二元、三层阶梯、单鲨）
                switch ((String) customLeg.get("productType")) {
                    case "Vanilla":
                        if (ParseUtils.converToBigDecimal(customLeg.get("strike")).compareTo(BigDecimal.ZERO) == 0) {
                            if (ParseUtils.converToBigDecimal4(customLeg.get("strikePercentage")).compareTo(BigDecimal.ZERO) == 1) {
                                updateMap.put("strikePrice", ParseUtils.converToBigDecimal4(customLeg.get("strikePercentage")).multiply(dpClose).setScale(2,BigDecimal.ROUND_HALF_UP));
                            }
                        }
                        break;
                    case "Digital":
                        JSONObject digital = (JSONObject) customLeg.get("digital");
                        JSONObject trigger = (JSONObject) digital.get("trigger");
                        if (ParseUtils.converToBigDecimal(trigger.get("level")).compareTo(BigDecimal.ZERO) == 0) {
                            if (ParseUtils.converToBigDecimal4(trigger.get("levelPercentage")).compareTo(BigDecimal.ZERO) == 1) {
                                updateMap.put("strikePrice", ParseUtils.converToBigDecimal4(trigger.get("levelPercentage")).multiply(dpClose).setScale(2,BigDecimal.ROUND_HALF_UP));
                            }
                        }
                        break;
                    case "MultilayerDigital" :
                        if (instrument.getInitProductType().equals("MultiDigital")) {
                            JSONArray priceRanges = (JSONArray) customLeg.get("priceRanges");
                            JSONObject index = (JSONObject) priceRanges.get(1);
                            if (ParseUtils.converToBigDecimal(index.get("floorPrice")).compareTo(BigDecimal.ZERO) == 0) {
                                if (ParseUtils.converToBigDecimal4(index.get("floorPricePecentage")).compareTo(BigDecimal.ZERO) == 1) {
                                    BigDecimal lowStrikePercentage = ParseUtils.converToBigDecimal4(index.get("floorPricePecentage"));
                                    updateMap.put("lowStrikePrice", lowStrikePercentage.multiply(dpClose).setScale(2, BigDecimal.ROUND_HALF_UP));
                                }
                            }
                            if (ParseUtils.converToBigDecimal(index.get("capPrice")).compareTo(BigDecimal.ZERO) == 0) {
                                if (ParseUtils.converToBigDecimal4(index.get("capPricePecentage")).compareTo(BigDecimal.ZERO) == 1) {
                                    BigDecimal StrikePercentage = ParseUtils.converToBigDecimal4(index.get("capPricePecentage"));
                                    updateMap.put("strikePrice", StrikePercentage.multiply(dpClose).setScale(2, BigDecimal.ROUND_HALF_UP));
                                }
                            }
                        }
                        if (instrument.getInitProductType().equals("DoubleDigital")) {
                            JSONArray priceRanges = (JSONArray) customLeg.get("priceRanges");
                            JSONObject index = (JSONObject) priceRanges.get(0);
                            if (ParseUtils.converToBigDecimal(index.get("capPrice")).compareTo(BigDecimal.ZERO) == 0) {
                                if (ParseUtils.converToBigDecimal4(index.get("capPricePecentage")).compareTo(BigDecimal.ZERO) == 1) {
                                    BigDecimal StrikePercentage = ParseUtils.converToBigDecimal4(index.get("capPricePecentage"));
                                    updateMap.put("strikePrice", StrikePercentage.multiply(dpClose).setScale(2, BigDecimal.ROUND_HALF_UP));
                                }
                            }
                        }
                        break;
                    case "SingleSharkFin":
                        JSONObject unTrigger = (JSONObject) customLeg.get("unTrigger");
                        JSONObject vanillaEuropean = (JSONObject) unTrigger.get("vanillaEuropean");
                        if (ParseUtils.converToBigDecimal(vanillaEuropean.get("strike")).compareTo(BigDecimal.ZERO) == 0) {
                            if (ParseUtils.converToBigDecimal4(vanillaEuropean.get("strikePercentage")).compareTo(BigDecimal.ZERO) == 1) {
                                BigDecimal strikePercentage = ParseUtils.converToBigDecimal4(vanillaEuropean.get("strikePercentage"));
                                updateMap.put("strikePrice", strikePercentage.multiply(dpClose).setScale(2, BigDecimal.ROUND_HALF_UP));
                            }
                        }
                        JSONObject knock = (JSONObject) customLeg.get("knock");
                        JSONObject trigger1 = (JSONObject) knock.get("trigger");
                        BigDecimal triggerRate = ParseUtils.converToBigDecimal4(trigger1.get("levelPercentage"));
                        BigDecimal triggerPrice = ParseUtils.converToBigDecimal(trigger1.get("level"));
                        if (triggerPrice.compareTo(BigDecimal.ZERO) != 0) {
                            updateMap.put("triggerPrice1", triggerPrice);
                        } else {
                            updateMap.put("triggerPrice1", triggerRate.multiply(dpClose).setScale(2,BigDecimal.ROUND_HALF_UP));
                        }

                        break;
                    case "RangeAccrual":
                        JSONObject pFormInstrumentObject = JSONObject.parseObject(pFormInstrument, JSONObject.class);
                        JSONObject singleSection = (JSONObject) pFormInstrumentObject.get("singleSection");
                        BigDecimal floorPrice = ParseUtils.converToBigDecimal(singleSection.get("floorPrice"));
                        BigDecimal floorRate = ParseUtils.converToBigDecimal4(singleSection.get("floorRate"));
                        BigDecimal capPrice = ParseUtils.converToBigDecimal(singleSection.get("capPrice"));
                        BigDecimal capRate = ParseUtils.converToBigDecimal4(singleSection.get("capRate"));
                        if (floorPrice.compareTo(BigDecimal.ZERO) ==0) {
                            updateMap.put("triggerPrice2", floorRate.divide(new BigDecimal(100), 4, BigDecimal.ROUND_HALF_UP).multiply(dpClose).setScale(2, BigDecimal.ROUND_HALF_UP));
                        }
                        if (capPrice.compareTo(BigDecimal.ZERO) ==0) {
                            updateMap.put("triggerPrice1", capRate.divide(new BigDecimal(100), 4, BigDecimal.ROUND_HALF_UP).multiply(dpClose).setScale(2, BigDecimal.ROUND_HALF_UP));
                        }
                        break;
                    default:
                        break;
                }
                //修改条框中的strike和strikePercentage
                Map<String, String> replaceMap = adjustStrikePercentageAndStrike(pCalc, pForm, pFormInstrument, dpClose);
                pCalc = replaceMap.get("pCalc");
                pForm = replaceMap.get("pForm");
                pFormInstrument = replaceMap.get("pFormInstrument");

                // 替换期初价格
                if ( ParseUtils.converToBigDecimal(underlyer.get("spotPrice")).compareTo(BigDecimal.ZERO) == 0 ) {
                    Trade trade = new Trade();
                    trade.setPrice(dpClose);
                    trade.setTradeId((String) structMap.get("TRADE_ID"));
                    tradeMapper.updateTrade(trade);
                    String spotString = "\"spotPrice\":" + dpClose.toString();
                    pCalc = pCalc.replace("\"spotPrice\":0", spotString);
                    pForm = pForm.replace("\"spotPrice\":0", spotString);
                    pFormInstrument = pFormInstrument.replace("\"spotPrice\":0", spotString);
                    pForm = pForm.replace("\"priceOnWait\":\"1\"", "\"priceOnWait\":\"0\"");
                    pFormInstrument = pFormInstrument.replace("\"priceOnWait\":\"1\"", "\"priceOnWait\":\"0\"");
                }

                // 获取交易数量
                if (ParseUtils.converToBigDecimal(customLeg.get("optionEntitlement")).compareTo(BigDecimal.ZERO) == 0) {
                    String countString = "\"optionEntitlement\":"+ notinal.divide(dpClose, 2, BigDecimal.ROUND_HALF_UP).toString();
                    String countStringCalc = "\"optionEntitlement\":"+ notinal.divide(dpClose, 2, BigDecimal.ROUND_HALF_UP).toString();
                    if (((String) customLeg.get("productType")).equals("SingleSharkFin") ) {
                        countStringCalc = "\"optionEntitlement\":"+ notinal.divide(dpClose, 10, BigDecimal.ROUND_HALF_UP).toString();
                    }
                    pCalc = pCalc.replace("\"optionEntitlement\":0", countStringCalc);
                    pForm = pForm.replace("\"optionEntitlement\":0", countString);
                    pFormInstrument = pFormInstrument.replace("\"optionEntitlement\":0", countString);
                }

                updateMap.put("tradeId", structMap.get("TRADE_ID"));
                updateMap.put("pCalc", pCalc);
                updateMap.put("pForm", pForm);
                updateMap.put("pFormInstrument", pFormInstrument);
                tequityStructureMapper.updateTequityStructure(updateMap);
            }
        }
    }

    private Map<String, String> adjustStrikePercentageAndStrike(String pCalc, String pForm, String pFormInstrument, BigDecimal dpClose) {

        Instrument instrument = JSONObject.parseObject(pCalc, Instrument.class);
        JSONObject termsheet = instrument.getTermsheet();
        JSONArray customLegs = (JSONArray) instrument.getTermsheet().get("customLegs");
        JSONObject customLeg = (JSONObject) customLegs.get(0);

        JSONObject pFormInstrumentObj = JSONObject.parseObject(pFormInstrument, JSONObject.class);
        JSONObject pFormObj = JSONObject.parseObject(pForm, JSONObject.class);

        switch ((String) customLeg.get("productType")) {
            case "Vanilla":
                BigDecimal strike = ParseUtils.converToBigDecimal(customLeg.get("strike"));
                BigDecimal strikePercentage = ParseUtils.converToBigDecimal4(customLeg.get("strikePercentage"));
                if (strike.compareTo(BigDecimal.ZERO) == 1) {
                    BigDecimal strikePercentageCalc = strike.divide(dpClose, 4, BigDecimal.ROUND_HALF_UP);
                    BigDecimal strikePercentageCalc2 = strikePercentageCalc.multiply(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_HALF_UP);
                    customLeg.replace("strikePercentage", strikePercentageCalc);
                    pFormInstrumentObj.replace("strikePercentage", strikePercentageCalc2);
                    pFormObj.replace("strikePercentage", strikePercentageCalc2);
                    break;
                }
                if (strikePercentage.compareTo(BigDecimal.ZERO) == 1) {
                    BigDecimal strikeCalc = dpClose.multiply(strikePercentage).setScale(2, BigDecimal.ROUND_HALF_UP);
                    customLeg.replace("strike", strikeCalc);
                    pFormInstrumentObj.replace("strike", strikeCalc);
                    pFormObj.replace("strike", strikeCalc);
                    break;
                }
                break;
            case "Digital":
                JSONObject digital = (JSONObject) customLeg.get("digital");
                JSONObject trigger = (JSONObject) digital.get("trigger");
                BigDecimal level = ParseUtils.converToBigDecimal(trigger.get("level"));
                BigDecimal levelPercentage = ParseUtils.converToBigDecimal4(trigger.get("levelPercentage"));
                if (level.compareTo(BigDecimal.ZERO) == 1) {
                    BigDecimal strikePercentageCalc = level.divide(dpClose, 4, BigDecimal.ROUND_HALF_UP);
                    BigDecimal strikePercentageCalc2 = strikePercentageCalc.multiply(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_HALF_UP);
                    trigger.replace("levelPercentage", strikePercentageCalc);
                    digital.replace("trigger", trigger);
                    customLeg.replace("digital", digital);
                    pFormInstrumentObj.replace("strikePercentage", strikePercentageCalc2 );
                    pFormObj.replace("strikePercentage", strikePercentageCalc2 );
                    break;
                }
                if (levelPercentage.compareTo(BigDecimal.ZERO) == 1) {
                    String strikeCalc = dpClose.multiply(levelPercentage).setScale(2, BigDecimal.ROUND_HALF_UP).toString();
                    trigger.replace("level", strikeCalc);
                    digital.replace("trigger", trigger);
                    customLeg.replace("digital", digital);
                    pFormInstrumentObj.replace("strike", strikeCalc);
                    pFormObj.replace("strike", strikeCalc);
                    break;
                }
                break;
            case "MultilayerDigital" :
                if (instrument.getInitProductType().equals("MultiDigital")) {
                    JSONArray priceRanges = (JSONArray) customLeg.get("priceRanges");
                    JSONObject first = (JSONObject) priceRanges.get(0);
                    JSONObject second = (JSONObject) priceRanges.get(1);
                    JSONObject third = (JSONObject) priceRanges.get(2);
                    if (ParseUtils.converToBigDecimal(first.get("capPrice")).compareTo(BigDecimal.ZERO) == 1) {
                        BigDecimal capPricePercentage = ParseUtils.converToBigDecimal(first.get("capPrice")).divide(dpClose, 4, BigDecimal.ROUND_HALF_UP);
                        BigDecimal capPricePercentageCalc = capPricePercentage.multiply(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_HALF_UP);
                        first.replace("capPricePecentage", capPricePercentage);
                        pFormInstrumentObj.replace("lowStrikePercentage", capPricePercentageCalc );
                        pFormObj.replace("lowStrikePercentage", capPricePercentageCalc );
                    }
                    if (ParseUtils.converToBigDecimal(first.get("capPrice")).compareTo(BigDecimal.ZERO) == 0) {
                        if (ParseUtils.converToBigDecimal4(first.get("capPricePecentage")).compareTo(BigDecimal.ZERO) == 1) {
                            BigDecimal capPrice = ParseUtils.converToBigDecimal4(first.get("capPricePecentage")).multiply(dpClose).setScale(2, BigDecimal.ROUND_HALF_UP);
                            first.replace("capPrice", capPrice);
                            pFormInstrumentObj.replace("lowStrike", capPrice);
                            pFormObj.replace("lowStrike", capPrice);
                        }
                    }
                    if (ParseUtils.converToBigDecimal(second.get("capPrice")).compareTo(BigDecimal.ZERO) == 1) {
                        BigDecimal capPricePercentage = ParseUtils.converToBigDecimal(second.get("capPrice")).divide(dpClose, 4, BigDecimal.ROUND_HALF_UP);
                        BigDecimal capPricePercentageCalc = capPricePercentage.multiply(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_HALF_UP);
                        second.replace("capPricePecentage", capPricePercentage);
                        pFormInstrumentObj.replace("strikePercentage", capPricePercentageCalc );
                        pFormObj.replace("strikePercentage", capPricePercentageCalc );
                    }
                    if (ParseUtils.converToBigDecimal(second.get("capPrice")).compareTo(BigDecimal.ZERO) == 0) {
                        if (ParseUtils.converToBigDecimal4(second.get("capPricePecentage")).compareTo(BigDecimal.ZERO) == 1) {
                            BigDecimal capPrice = ParseUtils.converToBigDecimal4(second.get("capPricePecentage")).multiply(dpClose).setScale(2, BigDecimal.ROUND_HALF_UP);
                            second.replace("capPrice", capPrice);
                            pFormInstrumentObj.replace("lowStrike", capPrice);
                            pFormObj.replace("lowStrike", capPrice);
                        }
                    }
                    if (ParseUtils.converToBigDecimal(second.get("floorPrice")).compareTo(BigDecimal.ZERO) == 1) {
                        BigDecimal floorPricePercentage = ParseUtils.converToBigDecimal(second.get("floorPrice")).divide(dpClose, 4, BigDecimal.ROUND_HALF_UP);
                        second.replace("floorPricePecentage", floorPricePercentage);
                    }
                    if (ParseUtils.converToBigDecimal(second.get("floorPrice")).compareTo(BigDecimal.ZERO) == 0) {
                        if (ParseUtils.converToBigDecimal4(second.get("floorPricePecentage")).compareTo(BigDecimal.ZERO) == 1) {
                            BigDecimal floorPrice = ParseUtils.converToBigDecimal4(second.get("floorPricePecentage")).multiply(dpClose).setScale(2, BigDecimal.ROUND_HALF_UP);
                            second.replace("floorPrice", floorPrice);
                        }
                    }
                    if (ParseUtils.converToBigDecimal(third.get("floorPrice")).compareTo(BigDecimal.ZERO) == 1) {
                        BigDecimal floorPricePercentage = ParseUtils.converToBigDecimal(third.get("floorPrice")).divide(dpClose, 4, BigDecimal.ROUND_HALF_UP);
                        third.replace("floorPricePecentage", floorPricePercentage);
                    }
                    if (ParseUtils.converToBigDecimal(third.get("floorPrice")).compareTo(BigDecimal.ZERO) == 0) {
                        if (ParseUtils.converToBigDecimal4(third.get("floorPricePecentage")).compareTo(BigDecimal.ZERO) == 1) {
                            BigDecimal floorPrice = ParseUtils.converToBigDecimal4(third.get("floorPricePecentage")).multiply(dpClose).setScale(2, BigDecimal.ROUND_HALF_UP);
                            third.replace("floorPrice", floorPrice);
                        }
                    }
                }
                if (instrument.getInitProductType().equals("DoubleDigital")) {
                    JSONArray priceRanges = (JSONArray) customLeg.get("priceRanges");
                    JSONObject first = (JSONObject) priceRanges.get(0);
                    JSONObject second = (JSONObject) priceRanges.get(1);
                    if (ParseUtils.converToBigDecimal(first.get("capPrice")).compareTo(BigDecimal.ZERO) == 1) {
                        BigDecimal capPricePercentage = ParseUtils.converToBigDecimal(first.get("capPrice")).divide(dpClose, 4, BigDecimal.ROUND_HALF_UP);
                        BigDecimal capPricePercentageCalc = capPricePercentage.multiply(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_HALF_UP);
                        first.replace("capPricePecentage", capPricePercentage);
                        pFormInstrumentObj.replace("strikePercentage", capPricePercentageCalc );
                        pFormObj.replace("strikePercentage", capPricePercentageCalc );
                    }
                    if (ParseUtils.converToBigDecimal(first.get("capPrice")).compareTo(BigDecimal.ZERO) == 0) {
                        if (ParseUtils.converToBigDecimal4(first.get("capPricePecentage")).compareTo(BigDecimal.ZERO) == 1) {
                            BigDecimal capPrice = ParseUtils.converToBigDecimal4(first.get("capPricePecentage")).multiply(dpClose).setScale(2, BigDecimal.ROUND_HALF_UP);
                            first.replace("capPrice", capPrice);
                            pFormInstrumentObj.replace("strike", capPrice);
                            pFormObj.replace("strike", capPrice);
                        }
                    }
                    if (ParseUtils.converToBigDecimal(second.get("floorPrice")).compareTo(BigDecimal.ZERO) == 1) {
                        BigDecimal floorPricePecentage = ParseUtils.converToBigDecimal(second.get("floorPrice")).divide(dpClose, 4, BigDecimal.ROUND_HALF_UP);
                        BigDecimal floorPricePecentageCalc = floorPricePecentage.multiply(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_HALF_UP);
                        second.replace("floorPricePecentage", floorPricePecentage);
                    }
                    if (ParseUtils.converToBigDecimal(second.get("floorPrice")).compareTo(BigDecimal.ZERO) == 0) {
                        if (ParseUtils.converToBigDecimal4(second.get("floorPricePecentage")).compareTo(BigDecimal.ZERO) == 1) {
                            BigDecimal floorPrice = ParseUtils.converToBigDecimal4(second.get("floorPricePecentage")).multiply(dpClose).setScale(2, BigDecimal.ROUND_HALF_UP);
                            second.replace("floorPrice", floorPrice);
                        }
                    }
                }
                break;
            case "SingleSharkFin":
                JSONObject unTrigger = (JSONObject) customLeg.get("unTrigger");
                JSONObject vanillaEuropean = (JSONObject) unTrigger.get("vanillaEuropean");
                BigDecimal strike1 = ParseUtils.converToBigDecimal(vanillaEuropean.get("strike"));
                BigDecimal strikePercentage1 = ParseUtils.converToBigDecimal4(vanillaEuropean.get("strikePercentage"));
                if (strike1.compareTo(BigDecimal.ZERO) == 1) {
                    BigDecimal strikePercentageCalc = strike1.divide(dpClose, 4, BigDecimal.ROUND_HALF_UP);
                    BigDecimal strikePercentageCalc2 = strikePercentageCalc.multiply(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_HALF_UP);
                    vanillaEuropean.replace("strikePercentage", strikePercentageCalc);
                    pFormInstrumentObj.replace("strikePercentage", strikePercentageCalc2 );
                    pFormObj.replace("strikePercentage", strikePercentageCalc2 );
                }
                if (strike1.compareTo(BigDecimal.ZERO) == 0) {
                    if (strikePercentage1.compareTo(BigDecimal.ZERO) == 1) {
                        BigDecimal strikeCalc = strikePercentage1.multiply(dpClose).setScale(2, BigDecimal.ROUND_HALF_UP);
                        vanillaEuropean.replace("strike", strikeCalc);
                        pFormInstrumentObj.replace("strike", strikeCalc);
                        pFormObj.replace("strike", strikeCalc);
                    }
                }
                JSONObject knock = (JSONObject) customLeg.get("knock");
                JSONObject trigger1 = (JSONObject) knock.get("trigger");
                BigDecimal levelPercentage1 = ParseUtils.converToBigDecimal4(trigger1.get("levelPercentage"));
                BigDecimal level1 = ParseUtils.converToBigDecimal(trigger1.get("level"));
                if (level1.compareTo(BigDecimal.ZERO) == 1) {
                    BigDecimal triggerRate = level1.divide(dpClose, 4, BigDecimal.ROUND_HALF_UP);
                    BigDecimal triggerRateCalc = triggerRate.multiply(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_HALF_UP);
                    trigger1.replace("levelPercentage", triggerRateCalc.divide(new BigDecimal(100), 4, BigDecimal.ROUND_HALF_UP));
                    pFormInstrumentObj.replace("triggerRate", triggerRateCalc);
                    pFormObj.replace("triggerRate", triggerRateCalc);
                }
                if (level1.compareTo(BigDecimal.ZERO) == 0) {
                    if (levelPercentage1.compareTo(BigDecimal.ZERO) == 1) {
                        BigDecimal triggerPrice = levelPercentage1.multiply(dpClose).setScale(2, BigDecimal.ROUND_HALF_UP);
                        trigger1.replace("level", triggerPrice);
                        pFormInstrumentObj.replace("triggerPrice", triggerPrice);
                        pFormObj.replace("triggerPrice", triggerPrice);
                    }
                }
                break;
            case "RangeAccrual":
                JSONObject singleSection = (JSONObject) pFormInstrumentObj.get("singleSection");
                BigDecimal floorPrice = ParseUtils.converToBigDecimal(singleSection.get("floorPrice"));
                BigDecimal floorRate = ParseUtils.converToBigDecimal4(singleSection.get("floorRate"));
                BigDecimal capPrice = ParseUtils.converToBigDecimal(singleSection.get("capPrice"));
                BigDecimal capRate = ParseUtils.converToBigDecimal4(singleSection.get("capRate"));
                if (floorPrice.compareTo(BigDecimal.ZERO) !=0) {
                    singleSection.replace("floorRate", floorPrice.divide(dpClose, 4, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_HALF_UP));
                }
                if (floorPrice.compareTo(BigDecimal.ZERO) ==0) {
                    if (floorRate.compareTo(BigDecimal.ZERO) !=0) {
                        singleSection.replace("floorPrice", floorRate.divide(new BigDecimal(100), 4, BigDecimal.ROUND_HALF_UP).multiply(dpClose).setScale(2, BigDecimal.ROUND_HALF_UP));
                    }
                }
                if (capPrice.compareTo(BigDecimal.ZERO) !=0) {
                    singleSection.replace("capRate", capPrice.divide(dpClose, 4, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_HALF_UP));
                }
                if (capPrice.compareTo(BigDecimal.ZERO) ==0) {
                    if (capRate.compareTo(BigDecimal.ZERO) !=0) {
                        singleSection.replace("capPrice", capRate.divide(new BigDecimal(100),4, BigDecimal.ROUND_HALF_UP).multiply(dpClose).setScale(2, BigDecimal.ROUND_HALF_UP));
                    }
                }
                JSONArray sections = (JSONArray) pFormInstrumentObj.get("sections");
                for (Object section : sections) {
                    JSONObject sectionObj = (JSONObject) section;
                    BigDecimal floorPrice2 = ParseUtils.converToBigDecimal(sectionObj.get("floorPrice"));
                    BigDecimal floorRate2 = ParseUtils.converToBigDecimal4(sectionObj.get("floorRate"));
                    BigDecimal capPrice2 = ParseUtils.converToBigDecimal(sectionObj.get("capPrice"));
                    BigDecimal capRate2 = ParseUtils.converToBigDecimal4(sectionObj.get("capRate"));
                    if (floorPrice2.compareTo(BigDecimal.ZERO) !=0) {
                        sectionObj.replace("floorRate", floorPrice2.divide(dpClose, 4, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_HALF_UP));
                    }
                    if (floorPrice2.compareTo(BigDecimal.ZERO) ==0) {
                        if (floorRate2.compareTo(BigDecimal.ZERO) !=0) {
                            sectionObj.replace("floorPrice", floorRate2.divide(new BigDecimal(100), 4, BigDecimal.ROUND_HALF_UP).multiply(dpClose).setScale(2, BigDecimal.ROUND_HALF_UP));
                        }
                    }
                    if (capPrice2.compareTo(BigDecimal.ZERO) !=0) {
                        sectionObj.replace("capRate", capPrice2.divide(dpClose, 4, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_HALF_UP));
                    }
                    if (capPrice2.compareTo(BigDecimal.ZERO) ==0) {
                        if (capRate2.compareTo(BigDecimal.ZERO) !=0) {
                            sectionObj.replace("capPrice", capRate2.divide(new BigDecimal(100),4, BigDecimal.ROUND_HALF_UP).multiply(dpClose).setScale(2, BigDecimal.ROUND_HALF_UP));
                        }
                    }
                }

                JSONArray priceRanges = (JSONArray) customLeg.get("priceRanges");
                for (Object range : priceRanges) {
                    JSONObject priceRange = (JSONObject) range;
                    if (ParseUtils.converToBigDecimal4(priceRange.get("floorPrice")).compareTo(BigDecimal.ZERO) !=0 ) {
                        priceRange.replace("floorPriceRate",ParseUtils.converToBigDecimal(priceRange.get("floorPrice")).divide(dpClose, 4, BigDecimal.ROUND_HALF_UP));
                    }
                    if (ParseUtils.converToBigDecimal(priceRange.get("floorPrice")).compareTo(BigDecimal.ZERO) ==0 ) {
                        if (ParseUtils.converToBigDecimal4(priceRange.get("floorPriceRate")).compareTo(BigDecimal.ZERO) !=0 ) {
                            priceRange.replace("floorPrice",dpClose.multiply(ParseUtils.converToBigDecimal4(priceRange.get("floorPriceRate"))).setScale(2, BigDecimal.ROUND_HALF_UP));
                        }
                    }
                    if (ParseUtils.converToBigDecimal(priceRange.get("capPrice")).compareTo(BigDecimal.ZERO) !=0 ) {
                        priceRange.replace("capPriceRate",ParseUtils.converToBigDecimal(priceRange.get("capPrice")).divide(dpClose,4, BigDecimal.ROUND_HALF_UP));
                    }
                    if (ParseUtils.converToBigDecimal(priceRange.get("capPrice")).compareTo(BigDecimal.ZERO) ==0 ) {
                        if (ParseUtils.converToBigDecimal4(priceRange.get("capPriceRate")).compareTo(BigDecimal.ZERO) !=0 ) {
                            priceRange.replace("capPrice",dpClose.multiply(ParseUtils.converToBigDecimal4(priceRange.get("capPriceRate"))).setScale(2, BigDecimal.ROUND_HALF_UP));
                        }
                    }
                }
                customLeg.replace("priceRanges", priceRanges);
                break;
            default:
                break;
        }
        customLegs.set(0, customLeg);
        termsheet.replace("customLegs", customLegs);
        instrument.setTermsheet(termsheet);
        HashMap<String, String> map = new HashMap<>();
        map.put("pCalc", JSON.toJSONString(instrument));
        map.put("pForm", JSON.toJSONString(pFormObj));
        map.put("pFormInstrument", JSON.toJSONString(pFormInstrumentObj));
        return map;
    }

}
